home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Games Collection 1 / software vault.zip / software vault / CDR10 / XLIB06.ZIP / XMAIN.ASM < prev    next >
Assembly Source File  |  1993-10-04  |  47KB  |  1,540 lines

  1. ;-----------------------------------------------------------------------
  2. ; MODULE XMAIN
  3. ;
  4. ; Initialization, panning and split screen functions for all MODE X 256
  5. ; Color resolutions
  6. ;
  7. ; Compile with Tasm.
  8. ; C callable.
  9. ;
  10. ;
  11. ; ****** XLIB - Mode X graphics library                ****************
  12. ; ******                                               ****************
  13. ; ****** Written By Themie Gouthas                     ****************
  14. ;
  15. ; egg@dstos3.dsto.gov.au
  16. ; teg@bart.dsto.gov.au
  17. ;
  18. ; MODIFICATIONS:
  19. ;  26-9-92:          Pel panning code added
  20. ;  Dates forgotten:  Numerous ;^)
  21. ;  05-10-93:         Timer synchronized vsync handling extensions
  22. ;                      and tripple buffering - Tore Jahn Bastiansen
  23. ;                      (toreba@ifi.uio.no) for the
  24. ;-----------------------------------------------------------------------
  25.  
  26.  
  27. include xlib.inc
  28. include xmain.inc
  29.  
  30.  
  31.     .data
  32.  
  33.  
  34. ; Mode X CRTC register tweaks for various resolutions
  35.  
  36.  
  37. LABEL X256Y200 word
  38.         db      0e3h    ; dot clock
  39.         db      8       ; Number of CRTC Registers to update
  40.     dw      05f00h  ; horz total
  41.     dw      03f01h  ; horz displayed
  42.     dw      04202h  ; start horz blanking
  43.     dw      09f03h  ; end horz blanking
  44.     dw      04c04h  ; start h sync
  45.     dw      00005h  ; end h sync
  46.     dw      00014h  ; turn off dword mode
  47.     dw      0e317h  ; turn on byte mode
  48.     dw      256
  49.     dw      200
  50.  
  51.  
  52. LABEL X256Y240 word
  53.     db      0e3h    ; dot clock
  54.     db      16      ; Number of CRTC Registers to update
  55.     dw      05f00h  ; horz total
  56.     dw      03f01h  ; horz displayed
  57.     dw      04202h  ; start horz blanking
  58.     dw      09f03h  ; end horz blanking
  59.     dw      04c04h  ; start h sync
  60.     dw      00005h  ; end h sync
  61.     dw      00d06h  ; vertical total
  62.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  63.     dw      04109h  ; cell height (2 to double-scan)
  64.     dw      0ea10h  ; v sync start
  65.     dw      0ac11h  ; v sync end and protect cr0-cr7
  66.     dw      0df12h  ; vertical displayed
  67.     dw      00014h  ; turn off dword mode
  68.     dw      0e715h  ; v blank start
  69.     dw      00616h  ; v blank end
  70.     dw      0e317h  ; turn on byte mode
  71.     dw      256
  72.         dw      240
  73.  
  74.  
  75. X320Y200 label  word
  76.     db      00      ; 0e3h    ; dot clock
  77.     db      02      ; Number of CRTC Registers to update
  78.     dw      00014h  ; turn off dword mode
  79.     dw      0e317h  ; turn on byte mode
  80.     dw      320     ; width
  81.     dw      200     ; height
  82.  
  83. X320Y240 label  word
  84.     db      0e3h    ; dot clock
  85.     db      10      ; Number of CRTC Registers to update
  86.     dw      00d06h  ; vertical total
  87.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  88.     dw      04109h  ; cell height (2 to double-scan)
  89.     dw      0ea10h  ; v sync start
  90.     dw      0ac11h  ; v sync end and protect cr0-cr7
  91.     dw      0df12h  ; vertical displayed
  92.     dw      00014h  ; turn off dword mode
  93.     dw      0e715h  ; v blank start
  94.     dw      00616h  ; v blank end
  95.     dw      0e317h  ; turn on byte mode
  96.     dw      320     ; width
  97.     dw      240     ; height
  98.  
  99. X360Y200 label  word
  100.     db      0e7h    ; dot clock
  101.     db      08      ; Number of CRTC Registers to update
  102.     dw      06b00h  ; horz total
  103.     dw      05901h  ; horz displayed
  104.     dw      05a02h  ; start horz blanking
  105.     dw      08e03h  ; end horz blanking
  106.     dw      05e04h  ; start h sync
  107.     dw      08a05h  ; end h sync
  108.     dw      00014h  ; turn off dword mode
  109.     dw      0e317h  ; turn on byte mode
  110.     dw      360     ; width
  111.     dw      200     ; height
  112.  
  113. X360Y240  label word
  114.     db      0e7h    ; dot clock
  115.     db      17      ; Number of CRTC Registers to update
  116.     dw      06b00h  ; horz total
  117.     dw      05901h  ; horz displayed
  118.     dw      05a02h  ; start horz blanking
  119.     dw      08e03h  ; end horz blanking
  120.     dw      05e04h  ; start h sync
  121.     dw      08a05h  ; end h sync
  122.     dw      00d06h  ; vertical total
  123.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  124.     dw      04109h  ; cell height (2 to double-scan)
  125.     dw      0ea10h  ; v sync start
  126.     dw      0ac11h  ; v sync end and protect cr0-cr7
  127.     dw      0df12h  ; vertical displayed
  128.     dw      02d13h  ; offset;
  129.     dw      00014h  ; turn off dword mode
  130.     dw      0e715h  ; v blank start
  131.     dw      00616h  ; v blank end
  132.     dw      0e317h  ; turn on byte mode
  133.     dw      360
  134.     dw      240
  135.  
  136. X376Y282 label word
  137.     db      0e7h
  138.     db      18
  139.     dw      06e00h  ; horz total
  140.     dw      05d01h  ; horz displayed
  141.     dw      05e02h  ; start horz blanking
  142.     dw      09103h  ; end horz blanking
  143.     dw      06204h  ; start h sync
  144.     dw      08f05h  ; end h sync
  145.     dw      06206h  ; vertical total
  146.     dw      0f007h  ; overflow
  147.     dw      06109h  ; cell height
  148.     dw      0310fh  ;
  149.     dw      03710h  ; v sync start
  150.     dw      08911h  ; v sync end and protect cr0-cr7
  151.     dw      03312h  ; vertical displayed
  152.     dw      02f13h  ; offset
  153.     dw      00014h  ; turn off dword mode
  154.     dw      03c15h  ; v blank start
  155.     dw      05c16h  ; v blank end
  156.     dw      0e317h  ; turn on byte mode
  157.     dw      376
  158.     dw      282
  159.  
  160. LABEL X256Y400 word
  161.     db      0e3h    ; dot clock
  162.     db      8       ; Number of CRTC Registers to update
  163.     dw      05f00h  ; horz total
  164.     dw      03f01h  ; horz displayed
  165.     dw      04202h  ; start horz blanking
  166.     dw      09f03h  ; end horz blanking
  167.     dw      04c04h  ; start h sync
  168.     dw      00005h  ; end h sync
  169.     dw      04009h  ; cell height
  170.     dw      00014h  ; turn off dword mode
  171.     dw      0e317h  ; turn on byte mode
  172.     dw      256
  173.     dw      400
  174.  
  175.  
  176. LABEL X256Y480 word
  177.     db      0e3h    ; dot clock
  178.     db      16      ; Number of CRTC Registers to update
  179.         dw      05f00h  ; horz total
  180.         dw      03f01h  ; horz displayed
  181.     dw      04202h  ; start horz blanking
  182.     dw      09f03h  ; end horz blanking
  183.     dw      04c04h  ; start h sync
  184.     dw      00005h  ; end h sync
  185.     dw      00d06h  ; vertical total
  186.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  187.     dw      04009h  ; cell height (2 to double-scan)
  188.     dw      0ea10h  ; v sync start
  189.     dw      0ac11h  ; v sync end and protect cr0-cr7
  190.     dw      0df12h  ; vertical displayed
  191.     dw      00014h  ; turn off dword mode
  192.     dw      0e715h  ; v blank start
  193.     dw      00616h  ; v blank end
  194.     dw      0e317h  ; turn on byte mode
  195.     dw      256
  196.     dw      480
  197.  
  198.  
  199.  
  200. X320Y400 label  word
  201.     db      0e3h    ; dot clock
  202.     db      03      ; Number of CRTC Registers to update
  203.     dw      04009h  ; cell height
  204.     dw      00014h  ; turn off dword mode
  205.     dw      0e317h  ; turn on byte mode
  206.     dw      320     ; width
  207.     dw      400     ; height
  208.  
  209. X320Y480 label  word
  210.     db      0e3h    ; dotclock
  211.     db      10      ; Number of CRTC Registers to update
  212.     dw      00d06h  ; vertical total
  213.     dw      03e07h  ; overflow (bit 8 of vertical counts)
  214.     dw      04009h  ; cell height (2 to double-scan)
  215.     dw      0ea10h  ; v sync start
  216.     dw      0ac11h  ; v sync end and protect cr0-cr7
  217.     dw      0df12h  ; vertical displayed
  218.     dw      00014h  ; turn off dword mode
  219.     dw      0e715h  ; v blank start
  220.     dw      00616h  ; v blank end
  221.     dw      0e317h  ; turn on byte mode
  222.     dw      320     ; width
  223.     dw      480     ; height
  224.  
  225. X360Y400 label  word
  226.     db      0e7h    ; dot clock
  227.     db      09      ; Number of CRTC Registers to update
  228.     dw      06b00h  ; horz total
  229.     dw      05901h  ; horz displayed
  230.     dw      05a02h  ; start horz blanking
  231.     dw      08e03h  ; end horz blanking
  232.     dw      05e04h  ; start h sync
  233.     dw      08a05h  ; end h sync
  234.     dw      04009h  ; cell height
  235.     dw      00014h  ; turn off dword mode
  236.     dw      0e317h  ; turn on byte mode
  237.     dw      360     ; width
  238.     dw      400     ; height
  239.  
  240.  
  241.  
  242. X360Y480  label word
  243.     db      0e7h
  244.     db      17
  245.     dw      06b00h  ; horz total
  246.     dw      05901h  ; horz displayed
  247.     dw      05a02h  ; start horz blanking
  248.     dw      08e03h  ; end horz blanking
  249.     dw      05e04h  ; start h sync
  250.     dw      08a05h  ; end h sync
  251.     dw      00d06h  ; vertical total
  252.     dw      03e07h  ; overflow
  253.     dw      04009h  ; cell height
  254.     dw      0ea10h  ; v sync start
  255.     dw      0ac11h  ; v sync end and protect cr0-cr7
  256.     dw      0df12h  ; vertical displayed
  257.     dw      02d13h  ; offset
  258.     dw      00014h  ; turn off dword mode
  259.     dw      0e715h  ; v blank start
  260.     dw      00616h  ; v blank end
  261.     dw      0e317h  ; turn on byte mode
  262.     dw      360
  263.     dw      480
  264.  
  265. X360Y360  label word
  266.     db      0e7h
  267.     db      15
  268.     dw      06b00h  ; horz total
  269.     dw      05901h  ; horz displayed
  270.     dw      05a02h  ; start horz blanking
  271.     dw      08e03h  ; end horz blanking
  272.     dw      05e04h  ; start h sync
  273.     dw      08a05h  ; end h sync
  274.     dw      04009h  ; cell height
  275.     dw      08810h  ; v sync start
  276.     dw      08511h  ; v sync end and protect cr0-cr7
  277.     dw      06712h  ; vertical displayed
  278.     dw      02d13h  ; offset
  279.     dw      00014h  ; turn off dword mode
  280.     dw      06d15h  ; v blank start
  281.     dw      0ba16h  ; v blank end
  282.     dw      0e317h  ; turn on byte mode
  283.     dw      360
  284.     dw      360
  285.  
  286.  
  287. X376Y308 label word
  288.     db      0e7h
  289.     db      18
  290.     dw      06e00h  ; horz total
  291.     dw      05d01h  ; horz displayed
  292.     dw      05e02h  ; start horz blanking
  293.     dw      09103h  ; end horz blanking
  294.     dw      06204h  ; start h sync
  295.     dw      08f05h  ; end h sync
  296.     dw      06206h  ; vertical total
  297.     dw      00f07h  ; overflow
  298.     dw      04009h  ;
  299.     dw      0310fh  ;
  300.     dw      03710h  ; v sync start
  301.     dw      08911h  ; v sync end and protect cr0-cr7
  302.     dw      03312h  ; vertical displayed
  303.     dw      02f13h  ; offset
  304.     dw      00014h  ; turn off dword mode
  305.     dw      03c15h  ; v blank start
  306.     dw      05c16h  ; v blank end
  307.     dw      0e317h  ; turn on byte mode
  308.     dw      376
  309.     dw      308
  310.  
  311. X376Y564 label word
  312.     db      0e7h
  313.     db      18
  314.     dw      06e00h  ; horz total
  315.     dw      05d01h  ; horz displayed
  316.     dw      05e02h  ; start horz blanking
  317.     dw      09103h  ; end horz blanking
  318.     dw      06204h  ; start h sync
  319.     dw      08f05h  ; end h sync
  320.     dw      06206h  ; vertical total
  321.     dw      0f007h  ; overflow
  322.     dw      06009h  ;
  323.     dw      0310fh  ;
  324.     dw      03710h  ; v sync start
  325.     dw      08911h  ; v sync end and protect cr0-cr7
  326.     dw      03312h  ; vertical displayed
  327.     dw      02f13h  ; offset
  328.     dw      00014h  ; turn off dword mode
  329.     dw      03c15h  ; v blank start
  330.     dw      05c16h  ; v blank end
  331.     dw      0e317h  ; turn on byte mode
  332.     dw      376
  333.     dw      564
  334.  
  335. LAST_X_MODE         equ    13
  336. ModeTable label word    ; Mode X tweak table
  337.     dw      offset X320Y200
  338.     dw      offset X320Y240
  339.     dw      offset X360Y200
  340.     dw      offset X360Y240
  341.     dw      offset X376Y282
  342.     dw      offset X320Y400
  343.     dw      offset X320Y480
  344.     dw      offset X360Y400
  345.     dw      offset X360Y480
  346.     dw      offset X360Y360
  347.     dw      offset X376Y308
  348.     dw      offset X376Y564
  349.     dw      offset X256Y200
  350.     dw      offset X256Y240
  351.  
  352.  
  353. PARAMS label byte
  354.  
  355.     _CurrXMode               dw 0   ; Current graphics mode index
  356.     _InGraphics              db 0   ; Flag indicating graphics activity
  357.     _ScrnPhysicalByteWidth   dw 0   ; Physical width in bytes of screen
  358.     _ScrnPhysicalPixelWidth  dw 0   ; Physical width in pixels of screen
  359.     _ScrnPhysicalHeight      dw 0   ; Physical Height of screen
  360.     _ErrorValue              db 0   ; Set after function calls
  361.  
  362.  
  363.     _SplitScrnActive         db 0   ; Flag indicating Split scrn activity
  364.     _DoubleBufferActive      dw 0   ; Flag indicating double buffering
  365.     _TrippleBufferActive     dw 0   ; Flag indicating tripple buffering
  366.  
  367.     _SplitScrnScanLine       dw 0   ; Split Screen's starting scan line
  368.     _SplitScrnVisibleHeight  dw 0   ; Split Screen's height on screen
  369.  
  370.     _SplitScrnOffs           dw 0   ; Offset in video ram of Split Screen
  371.                     ; always = 0
  372.     _Page0_Offs              dw 0   ; Ofset in video ram of Main virtual
  373.                     ; screen ( = 0 if no split screen
  374.                     ; otherwise = offset of first byte
  375.                     ; after split screen
  376.     _Page1_Offs              dw 0   ; Ofset in video ram of Second virtual
  377.                     ; screen ( = 0 if no split screen
  378.                     ; otherwise = offset of first byte
  379.                     ; after split screen
  380.                     ; = Page0_Offs if Doubble buffering
  381.                     ; not enabled
  382.     _Page2_Offs              dw 0
  383.  
  384.     _NonVisual_Offs          dw 0   ; Ofset in video ram of first byte
  385.                     ; of non visible ram
  386.     _ScrnLogicalByteWidth    dw 0   ; Logical width in bytes of screen
  387.     _ScrnLogicalPixelWidth   dw 0   ; Logical width in pixels of screen
  388.     _ScrnLogicalHeight       dw 0   ; Logical Height of screen
  389.  
  390.     _MaxScrollX              dw 0   ; Max X start position of Physical
  391.                     ; screen within virtual screen (in
  392.                     ; bytes)
  393.     _MaxScrollY              dw 0   ; Max Y start position of Physical
  394.                     ; screen within virtual screen
  395.  
  396.     _VisiblePageIdx          dw 0   ; Index of currently visible D.B.
  397.                     ; page
  398.  
  399.     PageAddrTable label word
  400.     _VisiblePageOffs         dw 0   ; Table containing starting offsets
  401.     _HiddenPageOffs          dw 0   ; of the double buffer pages
  402.     _WaitingPageOffs                 dw 0
  403.  
  404.     _TopClip                 dw 0   ; Clipping Rectangle
  405.     _BottomClip              dw 0   ;
  406.     _LeftClip                dw 0   ; Left/Right coordinates in bytes
  407.     _RightClip               dw 0   ;
  408.     _PhysicalStartByteX      dw 0   ; X byte coord of physical screen
  409.                     ; relative to virtual virtual screen
  410.     _PhysicalStartPixelX     dw 0   ; X pixel coord of physical screen
  411.                     ; relative to virtual screen
  412.     _PhysicalStartY          dw 0   ; Y pixel coord of physical screen
  413.                     ; relative to virtual screen
  414.  
  415. ; NEW
  416.     _VsyncHandlerActive     dw      0
  417.     _MouseRefreshFlag       dw      0
  418.     _MouseVsyncHandler      dd      0
  419.     _StartAddressFlag       dw      0
  420.     _WaitingStartLow        dw      0
  421.     _WaitingStartHigh       dw      0
  422.     _WaitingPelPan          dw      0
  423.     _VsyncPaletteStart      dw      0
  424.     _VsyncPaletteCount      dw      0
  425.     _VsyncPaletteBuffer     label  byte
  426.                 db  768  dup(?)
  427.  
  428.  
  429. PARAMS_END label byte
  430.  
  431. PARAM_COUNT equ ($-PARAMS)
  432.  
  433.  
  434. ; Index/data pairs for CRT Controller registers that differ between
  435. ; mode 13h and mode X.
  436.  
  437.     ;Pelpan values for 0,1,2,3 pixel panning to the left, respectively
  438.     PelPanMask              db      000h,002h,004h,006h
  439.  
  440. DoubleScanFlag db ?     ; Flag to indicate double scanned mode
  441.  
  442.     .code
  443.  
  444. ;-------------------------------------------------------------------------
  445. ; Local Logical Screen Width setting function
  446. ; cx = Requitrd Logical Width
  447. ;
  448. ; WARNING: no registers are preserved
  449.  
  450. SetLogicalScrWidth proc
  451.     mov   dx,CRTC_INDEX
  452.     mov   al,CRTC_OFFSET
  453.     out   dx,al
  454.     inc   dx
  455.  
  456.     mov   ax,cx
  457.     cmp   ax,[_ScrnPhysicalPixelWidth]; Is logical width >= physical width
  458.     jge   @@ValidLogicalWidth          ; yes - continue
  459.     mov   ax,bx                        ; no - set logical width = physical
  460.  
  461. @@ValidLogicalWidth:
  462.     shr   ax,3
  463.     out   dx,al
  464.  
  465.     ; The EXACT logical pixel width may not have been possible since
  466.     ; it should be divisible by 8. Round down to the closest possible
  467.     ; width and update the status variables
  468.  
  469.     shl   ax,1
  470.     mov   bx,ax
  471.     mov   [_ScrnLogicalByteWidth],ax  ; Store the byte width of virtual
  472.     mov   [_RightClip],ax             ; Set default Right clip column
  473.                       ; screen
  474.     sub   ax,[_ScrnPhysicalByteWidth] ; Calculate and store Max X position
  475.     shl   ax,2                        ; of physical screen in virtual
  476.     mov   [_MaxScrollX],ax            ; screen in pixels
  477.     mov   ax,bx                       ; set ax to byte width of virt scrn
  478.     shl   ax,2                        ; convert to pixels
  479.     mov   [_ScrnLogicalPixelWidth],ax ; store virt scrn pixel width
  480.     mov   cx,ax                       ; save ax (return value)
  481.  
  482.     ; calculate no. non split screen rows in video ram
  483.  
  484.     mov   ax,0ffffh                ; cx = Maximum video ram offset
  485.     sub   dx,dx                    ; DX:AX is divide operand,  set DX = 0
  486.     div   bx                       ; divide ax by ScrnLogicalByteWidth
  487.     mov   [_ScrnLogicalHeight],ax  ; Save Screen Logical Height
  488.     mov   [_BottomClip],ax         ; Set default bottom clip row
  489.     sub   ax,[_ScrnPhysicalHeight] ; Update the maximum Y position of
  490.     mov   [_MaxScrollY],ax         ; Physical screen in logical screen
  491.     mov   ax,cx                    ; restore ax (return value)
  492.  
  493.     ; calculate initial NonVisual
  494.     mov  ax,[_ScrnLogicalByteWidth]
  495.     mul  [_ScrnPhysicalHeight]
  496.     mov  [_NonVisual_Offs],ax
  497.  
  498. @@Done: ret
  499. SetLogicalScrWidth endp
  500.  
  501. clear_vram proc
  502.         push  di
  503.     mov   dx,SC_INDEX
  504.     mov   ax,0f02h
  505.     out   dx,ax               ; enable writes to all four planes
  506.     mov   ax,SCREEN_SEG       ; now clear all display memory, 8 pixels
  507.     mov   es,ax               ; at a time
  508.     sub   di,di               ; point ES:DI to display memory
  509.  
  510.     WaitVsyncEnd
  511.  
  512.     sub   ax,ax               ; clear to zero-value pixels
  513.     mov   cx,0FFFFh           ; # of words in display memory
  514.     rep   stosw               ; clear all of display memory
  515.         pop   di
  516.     ret
  517. clear_vram endp
  518.  
  519.  
  520.  
  521. ;-----------------------------------------------------------------------
  522. ; Mode X graphics mode set with a virtual screen
  523. ;   logical screen width.
  524. ; C near-callable as:
  525. ;
  526. ;    int x_set_mode(unsigned int mode,unsigned int WidthInPixels);
  527. ;
  528. ; returns the actual width of the allocated virtual screen in pixels
  529. ; if a valid mode was selected otherwise returns -1
  530. ;
  531. ; Saves virtual screen pixel width in _ScrnLogicalPixelWidth.
  532. ; Saves virtual screen byte  width in _ScrnLogicalByteWidth.
  533. ; Physical screen dimensions are set in _ScrnPhysicalPixelWidth,
  534. ; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight
  535. ;
  536. ;
  537. ; Modes:  0  = 320 x 200  (256 color)  NOTE: Some of these modes require
  538. ;         1  = 320 x 240  (256 color)     vertical size adjustment.
  539. ;         2  = 360 x 200  (256 color)
  540. ;         3  = 360 x 240  (256 color)
  541. ;         4  = 320 x 400  (256 color)
  542. ;         5  = 320 x 480  (256 color)
  543. ;         6  = 360 x 200  (256 color)
  544. ;         7  = 360 x 480  (256 color)
  545. ;         8  = 360 x 360  (256 color)
  546. ;         9  = 376 x 308  (256 color)
  547. ;         10 = 376 x 564  (256 color)
  548. ;
  549. ; Written by Themie Gouthas,
  550. ; parts adapted from M. Abrash code.
  551. ;------------------------------------------------------------------------
  552. _x_set_mode proc
  553.     ARG   mode:word,logicalscrwidth:word
  554.     push  bp      ;preserve caller's stack frame
  555.     mov   bp,sp
  556.  
  557.     push  si      ;preserve C register vars
  558.     push  di      ; (don't count on BIOS preserving anything)
  559.  
  560.     cld
  561.     mov   ax,ds
  562.     mov   es,ax
  563.     mov   di,offset PARAMS
  564.     xor   ax,ax
  565.     mov   cx,PARAM_COUNT
  566.     rep   stosb
  567.  
  568.     mov   cx,[mode]
  569.     cmp   cx,LAST_X_MODE        ; have we selected a valid mode
  570.     jle   @@ValidMode           ; Yes !
  571.  
  572.     mov   [_InGraphics],FALSE   ; No return -1
  573.     mov   ax,-1
  574.     pop   di
  575.     pop   si
  576.     pop   bp
  577.     ret
  578.  
  579. @@ValidMode:
  580.  
  581.     mov   [_CurrXMode],cx
  582.     mov   [_InGraphics],TRUE
  583.  
  584.     xor   al,al
  585.     cmp   cx,3
  586.     jg    @@SetDoubleScanFlag
  587.     mov   al,TRUE
  588. @@SetDoubleScanFlag:
  589.     mov   [DoubleScanFlag],al
  590.     push  cx                    ; some bios's dont preserve cx
  591.  
  592.     call  clear_vram
  593.  
  594.     mov   ax,13h                ; let the BIOS set standard 256-color
  595.     int   10h                   ;  mode (320x200 linear)
  596.  
  597.  
  598.     pop   cx
  599.  
  600.     mov   dx,SC_INDEX
  601.     mov   ax,0604h
  602.     out   dx,ax                 ; disable chain4 mode
  603.     mov   ax,0100h
  604.     out   dx,ax                 ; synchronous reset while setting Misc
  605.                     ;  Output for safety, even though clock
  606.                     ;  unchanged
  607.  
  608.     mov   bx,offset ModeTable
  609.     shl   cx,1
  610.     add   bx,cx
  611.     mov   si, word ptr [bx]
  612.     lodsb
  613.  
  614.     or    al,al
  615.     jz    @@DontSetDot
  616.     mov   dx,MISC_OUTPUT
  617.     out   dx,al               ; select the dot clock and Horiz
  618.                   ;  scanning rate
  619. @@DontSetDot:
  620.     mov   dx,SC_INDEX
  621.     mov   ax,0300h
  622.     out   dx,ax               ; undo reset (restart sequencer)
  623.  
  624.  
  625.     mov   dx,CRTC_INDEX       ; reprogram the CRT Controller
  626.     mov   al,11h              ; VSync End reg contains register write
  627.     out   dx,al               ; protect bit
  628.     inc   dx                  ; CRT Controller Data register
  629.     in    al,dx               ; get current VSync End register setting
  630.     and   al,07fh             ; remove write protect on various
  631.     out   dx,al               ; CRTC registers
  632.     dec   dx                  ; CRT Controller Index
  633.     cld
  634.     xor   cx,cx
  635.     lodsb
  636.     mov   cl,al
  637.  
  638. @@SetCRTParmsLoop:
  639.     lodsw                     ; get the next CRT Index/Data pair
  640.     out   dx,ax               ; set the next CRT Index/Data pair
  641.     loop  @@SetCRTParmsLoop
  642.  
  643.     mov   dx,SC_INDEX
  644.     mov   ax,0f02h
  645.     out   dx,ax               ; enable writes to all four planes
  646.     mov   ax,SCREEN_SEG       ; now clear all display memory, 8 pixels
  647.     mov   es,ax               ; at a time
  648.     sub   di,di               ; point ES:DI to display memory
  649.     sub   ax,ax               ; clear to zero-value pixels
  650.     mov   cx,8000h            ; # of words in display memory
  651.     rep   stosw               ; clear all of display memory
  652.  
  653.     ;  Set pysical screen dimensions
  654.  
  655.     lodsw                               ; Load scrn pixel width
  656.     mov   [_ScrnPhysicalPixelWidth],ax  ;  from tweak table and store
  657.     mov   [_SplitScrnScanLine],ax       ; No splitscrn ==
  658.                         ; splitscrn=PhysicalscrnHeight
  659.     mov   bx,ax                         ; Copy width for later use
  660.     shr   ax,2                          ; Convert to byte width
  661.     mov   [_ScrnPhysicalByteWidth],ax   ; Store for later use
  662.     lodsw                               ; Load Screen Phys. Height
  663.     mov   [_ScrnPhysicalHeight],ax      ; Store for later use
  664.  
  665.  
  666.     ;  Mode X is set, now set the required logical page width.
  667.  
  668.     mov     cx,[logicalscrwidth]
  669.  
  670.     call    SetLogicalScrWidth
  671.  
  672.     pop     di      ;restore C register vars
  673.     pop     si
  674.     pop     bp      ;restore caller's stack frame
  675.     ret
  676. _x_set_mode endp
  677.  
  678. ;----------------------------------------------------------------------
  679. ; Mode X (256 color mode) set default access video plane
  680. ;
  681. ; C near-callable as:
  682. ;    void x_select_default_plane(unsigned char plane);
  683. ;
  684. ; Enables Read/Write access to a plane using general memory access
  685. ; methods
  686. ;
  687. ; Written by Themie Gouthas
  688. ;----------------------------------------------------------------------
  689. _x_select_default_plane proc
  690. ARG Plane:byte
  691.     push bp
  692.     mov  bp,sp       ; set up stack frame
  693.     mov  cl,byte ptr [Plane]
  694.  
  695.     ; SELECT WRITE PLANE
  696.     and  cl,011b              ;CL = plane
  697.     mov  ax,0100h + MAP_MASK  ;AL = index in SC of Map Mask reg
  698.     shl  ah,cl                ;set only the bit for the required
  699.                   ; plane to 1
  700.     mov  dx,SC_INDEX          ;set the Map Mask to enable only the
  701.     out  dx,ax                ; pixel's plane
  702.  
  703.     ; SELECT READ PLANE
  704.     mov  ah,cl                ;AH = plane
  705.     mov  al,READ_MAP          ;AL = index in GC of the Read Map reg
  706.     mov  dx,GC_INDEX          ;set the Read Map to read the pixel's
  707.     out  dx,ax                ; plane
  708.  
  709.     pop  bp
  710.     ret
  711. _x_select_default_plane endp
  712.  
  713.  
  714. ;----------------------------------------------------------------------
  715. ; Mode X (256 color mode) Set Mode X split screen starting row
  716. ; The split screen resides on the bottom half of the screen and has a
  717. ; starting address of A000:0000
  718. ;
  719. ; C near-callable as:
  720. ;    void x_set_splitscreen(unsigned int line);
  721. ;
  722. ; Updates _Page0_Offs to reflect the existence of the split screen region
  723. ; ie _MainScrnOffset is set to the offset of the first pixel beyond the split
  724. ; screen region
  725. ;
  726. ; Written by Themie Gouthas
  727. ;----------------------------------------------------------------------
  728.  
  729. _x_set_splitscreen proc
  730.     ARG Line:word
  731.     push bp
  732.     mov  bp,sp       ; set up stack frame
  733.     push si
  734.  
  735.     xor  si,si       ; si=0 -> x virtual page start coord
  736.  
  737.     cmp  [_DoubleBufferActive],0
  738.     jne   @@error
  739.  
  740.     cmp  [_SplitScrnActive],0
  741.     je   @@NotPreviouslyCalled
  742.  
  743. @@error:
  744.     mov  [_ErrorValue],ERROR
  745.     pop  si
  746.     pop  bp          ; Return if previously called
  747.     ret
  748.  
  749. @@NotPreviouslyCalled:
  750.  
  751.     ; Turn on split screen pal pen suppression, so the split screen
  752.     ; wo'nt be subject to pel panning as is the non split screen portion.
  753.  
  754.     mov  dx,INPUT_STATUS_0
  755.     in   al,dx                  ; Reset the AC Index/Data toggle to
  756.                     ;  index state
  757.     mov  al,AC_MODE_CONTROL+20h ; Bit 5 set to prevent screen blanking
  758.     mov  dx,AC_INDEX            ; Point AC to Index/Data register
  759.     out  dx,al
  760.     inc  dx                     ; Point to AC Data reg (for reads only)
  761.     in   al,dx                  ; Get the current AC Mode Control reg
  762.     or   al,20h                 ; Enable split scrn Pel panning suppress.
  763.     dec  dx                     ; Point to AC Index/Data reg (for writes only)
  764.     out  dx,al                  ; Write the new AC Mode Control setting
  765.                     ;  with split screen pel panning
  766.                     ;  suppression turned on
  767.  
  768.     mov  [_PhysicalStartByteX],ax   ; Set the Phisical screen start
  769.     mov  [_PhysicalStartPixelX],ax  ; offset within virtual screen
  770.     mov  [_PhysicalStartY],ax
  771.     mov  [_SplitScrnActive],TRUE
  772.     mov  ax,[Line]
  773.     jns  @@NotNeg    ; Check that Split Scrn start scan line is +ve
  774.  
  775.     mov  ax,0        ; Since -ve set to 0
  776.  
  777. @@NotNeg:
  778.     mov  [_SplitScrnScanLine],ax   ; save the scanline
  779.  
  780.  
  781.  
  782.     or    [DoubleScanFlag],0
  783.     jz    @@NotDoubleScanned
  784.     shl   ax,1
  785.     dec   ax
  786. @@NotDoubleScanned:
  787.     ;mov  cl,[DoubleScanFlag]
  788.     ;shl  ax,cl            ; Mode X 200 and 240 line modes are actually
  789.                   ; 400 and 480 lines that are double scanned
  790.                   ; so for start scanline multiply required ModeX
  791.                   ; scan line by 2 if its a double scanned mode
  792.  
  793.  
  794.     mov  bx,ax            ; save the scanline
  795.  
  796.  
  797.     WaitVsyncStart        ; wait for vertical retrace
  798.  
  799.     cli                   ; Dont allow register setting to be interrupted
  800.     mov  dx,CRTC_INDEX
  801.     mov  ah,bl
  802.     mov  al,LINE_COMPARE
  803.     out  dx,ax            ; Bits 7-0 of the split screen scan line
  804.  
  805.     mov  ah,bh
  806.     and  ah,1
  807.     shl  ah,4
  808.     mov  al,OVERFLOW     ; Bit 4 of overflow register = Bit 8 of split
  809.     out  dx,al           ; screen scan line,
  810.     inc  dx              ; So using readability of VGA registers
  811.     in   al,dx           ; Read the OVERFLOW register, and set the
  812.     and  al, not 10h     ; bit corresponding to Bit 8 (above)
  813.     or   al,ah
  814.     out  dx,al
  815.  
  816.     dec  dx
  817.     mov  ah,bh
  818.     and  ah,2
  819.     ror  ah,3
  820.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  821.     out  dx,al             ; Bit 9 of split screen scan line
  822.     inc  dx                ; As we did before, update the apropriate
  823.     in   al,dx             ; bit without disturbing the rest
  824.     and  al, not 40h
  825.     or   al,ah
  826.     out  dx,al
  827.     sti                    ; Registers are set, so interrupts are safe
  828.  
  829.     mov  ax,[_ScrnPhysicalHeight]     ; Determine where the first byte
  830.     sub  ax,[_SplitScrnScanLine]      ; of the non split screen video ram
  831.     mov  [_SplitScrnVisibleHeight],ax ; starts and store it for reference
  832.  
  833.     mov  bx,[_ScrnLogicalByteWidth]
  834.     mul  bx
  835.     mov  [_Page0_Offs],ax
  836.     mov  [_Page1_Offs],ax
  837.     mov  [_Page2_Offs],ax
  838.  
  839.     ; calculate no. non split screen rows in video ram
  840.     mov  cx,0ffffh             ; cx = Maximum video ram offset
  841.     sub  cx,ax                 ; cx = cx - _Page0_Offs
  842.     xchg cx,ax                 ; swap cx and ax
  843.     sub  dx,dx                 ; DX:AX is divide operand,  set DX = 0
  844.     div  bx                    ; divide ax (prev cx) by
  845.                    ; ScrnLogicalByteWidth
  846.  
  847.     mov  [_ScrnLogicalHeight],ax     ; Save Screen Logical Height
  848.     cmp   ax,[_BottomClip]
  849.     jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
  850.     mov   [_BottomClip],ax
  851. @@BottomClipOK:
  852.     sub  ax,[_SplitScrnScanLine]     ; Update the maximum Y position of
  853.     mov  [_MaxScrollY],ax            ; Physical screen in logical screen
  854.  
  855.     xchg cx,ax                       ; restore original ax (MainScrnOfs)
  856.     mov  bh,al                       ; Set the visible screen start address
  857.     mov  ch,ah                       ; to the top left corner of the virtual
  858.     jmp  StartAddrEntry              ; screen
  859. _x_set_splitscreen      endp
  860.  
  861.  
  862. ;-----------------------------------------------------------------------
  863. ; Mode X (256 color mode) Page flip primer
  864. ; No clipping is performed.
  865. ; C near-callable as:
  866. ;
  867. ;    void x_page_flip(unsigned int x, unsigned int y);
  868. ;
  869. ; Swaps visible and hidden page offsets and then executes the SetStartAddr
  870. ; to achieve a page flip.
  871. ;
  872. ; SEE x_set_start_addr below
  873. ;
  874. ; Written by Themie Gouthas
  875. ;------------------------------------------------------------------------
  876.  
  877. _x_page_flip proc
  878.     ARG x:word,y:word
  879.     push  bp                  ;preserve caller's stack frame
  880.     mov   bp,sp               ;point to local stack frame
  881.     push  si
  882.  
  883.     mov  si,[x]
  884.     mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
  885.     mov  cx,[y]
  886.     mul  cx                             ; for Y
  887.     cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
  888.     je   @@DoubleBuffer
  889.     cmp  [_TrippleBufferActive],TRUE
  890.     jne   PageFlipEntry1
  891.  
  892. ; TrippleBuffer
  893.     mov  bx,[_HiddenPageOffs]
  894.     xchg bx,[_VisiblePageOffs]
  895.     xchg bx,[_WaitingPageOffs]
  896.     mov  [_HiddenPageOffs],bx
  897.     mov  bx,[_VisiblePageIdx]
  898.     inc  bx
  899.     cmp  bx,3
  900.     jne  @@IdxOk
  901.     xor  bx,bx
  902. @@IdxOk:
  903.     mov  [_VisiblePageIdx],bx
  904.     jmp  short PageFlipEntry2
  905. @@DoubleBuffer:
  906.     mov  bx,[_HiddenPageOffs]
  907.     xchg bx,[_VisiblePageOffs]          ; Swap the Page Offsete
  908.     xchg [_HiddenPageOffs],bx
  909.     xor  [_VisiblePageIdx],01h          ; Set the Visible page index
  910.     jmp  short PageFlipEntry2
  911. _x_page_flip endp
  912.  
  913.  
  914. ;-----------------------------------------------------------------------
  915. ; Mode X (256 color mode) Set Mode X non split screen start address
  916. ;   of logical screen.
  917. ; C near-callable as:
  918. ;
  919. ;    void x_set_start_addr(unsigned int x, unsigned int y);
  920. ;
  921. ; Params: StartOffset is offset of first byte of logical screen ram
  922. ;           (Useful if you want to double buffer by splitting your non
  923. ;            split screen video ram into 2 pages)
  924. ;        X,Y coordinates of the top left hand corner of the physical screen
  925. ;           within the logical screen
  926. ;           X must not exceed (Logical screen width - Physical screen width)
  927. ;           Y must not exceed (Logical screen height - Physical screen height)
  928. ;
  929. ;
  930. ; Written by Themie Gouthas,
  931. ; Parts addapted from M. Abrash code published in DDJ Mag.
  932. ;------------------------------------------------------------------------
  933. _x_set_start_addr proc
  934.     ARG x:word,y:word
  935.     push bp
  936.     mov  bp,sp
  937.     push si
  938.  
  939.     mov  si,[x]
  940.     mov  ax,[_ScrnLogicalByteWidth]     ; Calculate Offset increment
  941.     mov  cx,[y]                         ; for Y
  942.     mul  cx
  943.     cmp  [_DoubleBufferActive],TRUE     ; Do we have double buffering ?
  944.     je   @@PageResolution
  945.     cmp  [_TrippleBufferActive],TRUE
  946.     je   @@PageResolution
  947. PageFlipEntry1:
  948.     add  ax,[_Page0_Offs]               ; no - add page 0 offset
  949.     jmp  short @@AddColumn
  950.  
  951. PageFlipEntry2:
  952.  
  953.     mov  [_PhysicalStartPixelX],si
  954.     mov  [_PhysicalStartY],cx
  955.  
  956. @@PageResolution:
  957.     add  ax,[_VisiblePageOffs]          ; Add visible page offset
  958.  
  959. @@AddColumn:
  960.     mov  cx,si
  961.     shr  cx,2
  962.     mov  [_PhysicalStartByteX],cx
  963.     add  ax,cx                          ; add the column offset for X
  964.     mov  bh,al                          ; setup CRTC start addr regs and
  965.                         ; values in word registers for
  966.     mov  ch,ah                          ; fast word outs
  967.  
  968. StartAddrEntry:
  969.     mov  bl,ADDR_LOW
  970.     mov  cl,ADDR_HIGH
  971.     and  si,0003h             ; select pel pan register value for the
  972.     mov  ah,PelPanMask[si]    ; required x coordinate
  973.     mov  al,PEL_PANNING+20h
  974.     mov  si,ax
  975.  
  976.     cmp  [_VsyncHandlerActive],TRUE
  977.     jne   @@NoVsyncHandler
  978. ; NEW STUFF
  979. @@WaitLast:
  980.     cmp   [_StartAddressFlag],0
  981.     jne   @@WaitLast
  982.     cli
  983.     mov  [_WaitingStartLow],bx
  984.     mov  [_WaitingStartHigh],cx
  985.     mov  [_WaitingPelPan],si
  986.     mov  [_StartAddressFlag],1
  987.     sti
  988.     jmp  short @@Return
  989.  
  990. @@NoVsyncHandler:
  991.     mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse
  992. @@WaitDE:
  993.     in   al,dx
  994.     test al,01h
  995.     jnz  @@WaitDE            ;display enable is active low (0 = active)
  996.  
  997.     mov  dx,CRTC_INDEX
  998.     mov  ax,bx
  999.     cli
  1000.     out  dx,ax               ;start address low
  1001.     mov  ax,cx
  1002.     out  dx,ax               ;start address high
  1003.     sti
  1004.  
  1005. ; Now wait for vertical sync, so the other page will be invisible when
  1006. ; we start drawing to it.
  1007.     mov  dx,INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse
  1008. @@WaitVS:
  1009.     in   al,dx
  1010.     test al,08h
  1011.     jz @@WaitVS           ;display enable is active low (0 = active)
  1012.  
  1013.  
  1014.     mov  dx,AC_INDEX
  1015.     mov  ax,si                ; Point the attribute controller to pel pan
  1016.     cli
  1017.     out  dx,al                ; reg. Bit 5 also set to prevent blanking
  1018.     mov  al,ah
  1019.     out  dx,al                ; load new Pel Pan setting.
  1020.     sti
  1021.  
  1022. @@Return:
  1023.     mov  [_ErrorValue],OK
  1024.     pop  si
  1025.     pop  bp
  1026.     ret
  1027. _x_set_start_addr  endp
  1028.  
  1029.  
  1030. ;-----------------------------------------------------------------------
  1031. ; Mode X (256 color mode) Mode X split screen hide
  1032. ; C near-callable as:
  1033. ;
  1034. ;    void x_hide_splitscreen()
  1035. ;
  1036. ; Hides an existing split screen by setting its starting scan line to
  1037. ; the last physical screen scan line
  1038. ;
  1039. ; WARNING: Only to be used if SplitScrnLine has been previously called
  1040. ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
  1041. ;          the initial split screen is reserved and the size limitations
  1042. ;          of these modes means any change in the split screen scan line
  1043. ;          will encroach on the split screen ram
  1044. ;
  1045. ; Written by Themie Gouthas
  1046. ;------------------------------------------------------------------------
  1047.  
  1048. _x_hide_splitscreen proc
  1049.     push bp
  1050.     mov  bp,sp
  1051.  
  1052.     cmp  [_SplitScrnActive],TRUE
  1053.     je   @@SplitScreenEnabled
  1054.  
  1055. @@error:
  1056.     mov  [_ErrorValue],ERROR
  1057.     pop  bp
  1058.     ret
  1059.  
  1060. @@SplitScreenEnabled:
  1061.     cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
  1062.     jg   @@error
  1063.     mov  bx,[_ScrnPhysicalHeight]
  1064.  
  1065.     mov  ax,[_ScrnLogicalHeight]
  1066.     sub  ax,bx
  1067.     mov  [_MaxScrollY],ax
  1068.     xor  ax,ax
  1069.     mov  [_SplitScrnVisibleHeight],ax
  1070.  
  1071.     or    [DoubleScanFlag],0
  1072.     jz    @@NotDoubleScanned
  1073.     shl   bx,1
  1074.     dec   bx
  1075. @@NotDoubleScanned:
  1076.     ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes
  1077.     ;shl  bx,cl
  1078.  
  1079.     WaitVsyncStart               ; wait for vertical retrace
  1080.  
  1081.     cli                 ; Dont allow register setting to be interrupted
  1082.     mov  dx,CRTC_INDEX
  1083.     mov  ah,bl
  1084.     mov  al,LINE_COMPARE
  1085.     out  dx,ax          ; Bits 7-0 of the split screen scan line
  1086.  
  1087.     mov  ah,bh
  1088.     and  ah,1
  1089.     shl  ah,4
  1090.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  1091.     out  dx,al        ; screen scan line,
  1092.     inc  dx           ; So using readability of VGA registers
  1093.     in   al,dx        ; Read the OVERFLOW register, and set the
  1094.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  1095.     or   al,ah
  1096.     out  dx,al
  1097.  
  1098.     dec  dx
  1099.     mov  ah,bh
  1100.     and  ah,2
  1101.     ror  ah,3
  1102.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  1103.     out  dx,al             ; Bit 9 of split screen scan line
  1104.     inc  dx                ; As we did before, update the apropriate
  1105.     in   al,dx             ; bit without disturbing the rest
  1106.     and  al, not 40h
  1107.     or   al,ah
  1108.     out  dx,al
  1109.     sti                  ; Registers are set, so interrupts are safe
  1110.  
  1111. @@done:
  1112.  
  1113.     mov  [_ErrorValue],OK
  1114.     pop  bp
  1115.     ret
  1116. _x_hide_splitscreen endp
  1117.  
  1118. ;-----------------------------------------------------------------------
  1119. ; Mode X (256 color mode) Mode X split screen show
  1120. ; C near-callable as:
  1121. ;
  1122. ;    void x_show_splitscreen()
  1123. ;
  1124. ; Restores split screen start scan line to the initial split screen
  1125. ; starting scan line as set by SplitScrnLine.
  1126. ;
  1127. ; WARNING: Only to be used if SplitScrnLine has been previously called
  1128. ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
  1129. ;          the initial split screen is reserved and the size limitations
  1130. ;          of these modes means any change in the split screen scan line
  1131. ;          will encroach on the split screen ram
  1132. ;          Update: Now disabled for these modes
  1133. ;
  1134. ; Written by Themie Gouthas
  1135. ;------------------------------------------------------------------------
  1136.  
  1137.  
  1138. _x_show_splitscreen proc
  1139.     push bp
  1140.     mov  bp,sp
  1141.  
  1142.     cmp  [_SplitScrnActive],TRUE
  1143.     je   @@SplitScreenEnabled
  1144.  
  1145. @@error:
  1146.     mov  [_ErrorValue],ERROR
  1147.     pop  bp
  1148.     ret
  1149.  
  1150. @@SplitScreenEnabled:
  1151.     cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
  1152.     jg   @@error
  1153.  
  1154.     mov  bx,[_SplitScrnScanLine]
  1155.     mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
  1156.     sub  ax,bx
  1157.     mov  [_MaxScrollY],ax
  1158.  
  1159.     mov  ax,[_ScrnPhysicalHeight]
  1160.     sub  ax,bx
  1161.     mov  [_SplitScrnVisibleHeight],ax
  1162.  
  1163.     or    [DoubleScanFlag],0
  1164.     jz    @@NotDoubleScanned
  1165.     shl   bx,1
  1166.     dec   bx
  1167. @@NotDoubleScanned:
  1168.     ;mov  cl,[DoubleScanFlag]  ; Compensate for double scanned modes
  1169.     ;shl  bx,cl
  1170.     WaitVsyncStart               ; wait for vertical retrace
  1171.  
  1172.     cli                          ; Dont allow register setting to be interrupted
  1173.     mov  dx,CRTC_INDEX
  1174.     mov  ah,bl
  1175.     mov  al,LINE_COMPARE
  1176.     out  dx,ax                  ; Bits 7-0 of the split screen scan line
  1177.  
  1178.     mov  ah,bh
  1179.     and  ah,1
  1180.     shl  ah,4
  1181.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  1182.     out  dx,al        ; screen scan line,
  1183.     inc  dx           ; So using readability of VGA registers
  1184.     in   al,dx        ; Read the OVERFLOW register, and set the
  1185.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  1186.     or   al,ah
  1187.     out  dx,al
  1188.  
  1189.     dec  dx
  1190.     mov  ah,bh
  1191.     and  ah,2
  1192.     ror  ah,3
  1193.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  1194.     out  dx,al             ; Bit 9 of split screen scan line
  1195.     inc  dx                ; As we did before, update the apropriate
  1196.     in   al,dx             ; bit without disturbing the rest
  1197.     and  al, not 40h
  1198.     or   al,ah
  1199.     out  dx,al
  1200.     sti                  ; Registers are set, so interrupts are safe
  1201.  
  1202. @@Done:
  1203.     mov  [_ErrorValue],0
  1204.     pop  bp
  1205.     ret
  1206. _x_show_splitscreen endp
  1207.  
  1208.  
  1209. ;-----------------------------------------------------------------------
  1210. ; Mode X (256 color mode) Modify Mode X split screen starting scan line
  1211. ; C near-callable as:
  1212. ;
  1213. ;    void x_adjust_splitscreen(unsigned int ScanLine)
  1214. ;
  1215. ; Sets the split screen start scan line to a new scan line. Valid scan lines
  1216. ; are between the initial split screen starting scan line and the last
  1217. ; physical screen scan line.
  1218. ;
  1219. ; WARNING: Only to be used if SplitScrnLine has been previously called
  1220. ; WARNING: DO NOT USE with mode 5-11 (320x400-376x564). The memory for
  1221. ;          the initial split screen is reserved and the size limitations
  1222. ;          of these modes means any change in the split screen scan line
  1223. ;          will encroach on the split screen ram
  1224. ;          Update: Now disabled for these modes
  1225. ;
  1226. ;
  1227. ; Written by Themie Gouthas
  1228. ;------------------------------------------------------------------------
  1229.  
  1230.  
  1231. _x_adjust_splitscreen proc
  1232.     ARG   ScanLine
  1233.     push bp
  1234.     mov  bp,sp
  1235.  
  1236.     cmp  [_SplitScrnActive],TRUE
  1237.     je   @@SplitScreenEnabled
  1238.  
  1239. @@error:
  1240.     mov  [_ErrorValue],ERROR
  1241.     pop  bp
  1242.     ret
  1243.  
  1244. @@SplitScreenEnabled:
  1245.     cmp  [_CurrXMode],4          ; Do nothing for Modes > 2
  1246.     jg   @@error
  1247.     mov  bx,[ScanLine]            ; Is the required starting scan line
  1248.     cmp  bx,[_SplitScrnScanLine]  ; valid ?
  1249.     js   @@Done                   ; No - Then do nothing
  1250.  
  1251. @@ValidScanLine:
  1252.  
  1253.     mov  ax,[_ScrnLogicalHeight] ; Update Max Scroll Y
  1254.     sub  ax,bx
  1255.     mov  [_MaxScrollY],ax
  1256.  
  1257.     mov  ax,[_ScrnPhysicalHeight]
  1258.     sub  ax,bx
  1259.     mov  [_SplitScrnVisibleHeight],ax
  1260.  
  1261.     or    [DoubleScanFlag],0
  1262.     jz    @@NotDoubleScanned
  1263.     shl   bx,1
  1264.     dec   bx
  1265. @@NotDoubleScanned:
  1266.     ;mov  cl,[DoubleScanFlag]   ; Compensate for double scanned modes
  1267.     ;shl  bx,cl
  1268.  
  1269.     WaitVsyncStart      ; wait for vertical retrace
  1270.  
  1271.     cli                 ; Dont allow register setting to be interrupted
  1272.  
  1273.     mov  dx,CRTC_INDEX
  1274.     mov  ah,bl
  1275.     mov  al,LINE_COMPARE
  1276.     out  dx,ax          ; Bits 7-0 of the split screen scan line
  1277.  
  1278.     mov  ah,bh
  1279.     and  ah,1
  1280.     shl  ah,4
  1281.     mov  al,OVERFLOW  ; Bit 4 of overflow register = Bit 8 of split
  1282.     out  dx,al        ; screen scan line,
  1283.     inc  dx           ; So using readability of VGA registers
  1284.     in   al,dx        ; Read the OVERFLOW register, and set the
  1285.     and  al, not 10h  ; bit corresponding to Bit 8 (above)
  1286.     or   al,ah
  1287.     out  dx,al
  1288.  
  1289.     dec  dx
  1290.     mov  ah,bh
  1291.     and  ah,2
  1292.     ror  ah,3
  1293.     mov  al,MAX_SCAN_LINE  ; Bit 6 of max scan line register =
  1294.     out  dx,al             ; Bit 9 of split screen scan line
  1295.     inc  dx                ; As we did before, update the apropriate
  1296.     in   al,dx             ; bit without disturbing the rest
  1297.     and  al, not 40h
  1298.     or   al,ah
  1299.     out  dx,al
  1300.     sti                    ; Registers are set, so interrupts are safe
  1301. @@Done:
  1302.     mov  [_ErrorValue],OK
  1303.     pop   bp
  1304.     ret
  1305. _x_adjust_splitscreen endp
  1306.  
  1307.  
  1308.  
  1309. ;-----------------------------------------------------------------------
  1310. ; Mode X (256 color mode) Enable DoubleBuffering on non split screen area
  1311. ; C near-callable as:
  1312. ;
  1313. ;    int x_set_doublebuffer(unsigned int PageHeight);
  1314. ;
  1315. ; Params: PageHeight is the height of the virtual screen to double buffer
  1316. ;         Returns the closest possible height to the specified.
  1317. ;
  1318. ; Sets up two double buffering virtual pages
  1319. ; GLOBAL variables set:
  1320. ;
  1321. ;      _Page1_Offs              Offset of second virtual page
  1322. ;      _NonVisual_Offs          Offset of first non visible video ram byte
  1323. ;      _DoubleBufferActive      Flag
  1324. ;      _PageAddrTable           Table of Double buffering pages start offsets
  1325. ;      _ScrnLogicalHeight       Logical height of the double buffering pages
  1326. ;
  1327. ;
  1328. ; Written by Themie Gouthas
  1329. ;------------------------------------------------------------------------
  1330.  
  1331.  
  1332. _x_set_doublebuffer proc
  1333.        ARG PageHeight:word
  1334.        push  bp
  1335.        mov   bp,sp
  1336.  
  1337.        cmp   [_DoubleBufferActive],0
  1338.        je    @@OkToContinue
  1339. @error:
  1340.        mov   [_ErrorValue],ERROR
  1341.        pop   bp
  1342.        ret
  1343.  
  1344. @@OkToContinue:
  1345.        mov   [_VisiblePageIdx],0     ; Set visible Page to 0
  1346.        mov   ax,[_ScrnLogicalHeight] ; Set Maximum D.B. Page height to
  1347.        shr   ax,1                    ;   _ScrnLogicalHeight / 2
  1348.  
  1349.        mov   bx,[PageHeight]         ; Is the require D.B. Page Height
  1350.        cmp   ax,bx                   ;  > the Maximum  D.B. Page Height ?
  1351.  
  1352.        js    @@InvalidHeight         ; no  - jump
  1353.        mov   ax,bx                   ; yes - Set the D.B. Page height to
  1354.                      ;       to the maximum allowed.
  1355.  
  1356. @@InvalidHeight:
  1357.        mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to
  1358.                     ;  reflect the height of a D.B. page
  1359.        cmp   ax,[_BottomClip]
  1360.        jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
  1361.        mov   [_BottomClip],ax
  1362. @@BottomClipOK:
  1363.        push  ax
  1364.        mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second
  1365.        mov   cx,ax                      ;  D.B. Page in video ram
  1366.        mov   bx,[_Page0_Offs]
  1367.        mov   [_VisiblePageOffs],bx
  1368.  
  1369.        add   ax,bx
  1370.        mov   [_Page1_Offs],ax           ; Save it
  1371.        mov   [_HiddenPageOffs],ax
  1372.  
  1373.        add   ax,cx                      ; Calculate the offset of first byte
  1374.        mov   [_NonVisual_Offs],ax       ;  beyond the D.B. pages and save it
  1375.        mov   [_DoubleBufferActive],TRUE ; Set flag indicating D.B'ing mode on
  1376.  
  1377.        pop   ax
  1378.        sub   ax,[_ScrnPhysicalHeight]
  1379.        add   ax,[_SplitScrnVisibleHeight]
  1380.        mov   [_MaxScrollY],ax
  1381.  
  1382.        mov   ax,dx                      ; return the D.B. pages' height
  1383.        mov   [_ErrorValue],OK
  1384.        pop   bp
  1385.        ret
  1386. _x_set_doublebuffer endp
  1387.  
  1388.  
  1389. ;-----------------------------------------------------------------------
  1390. ; Mode X (256 color mode) Enable TrippleBuffering on non split screen area
  1391. ; C near-callable as:
  1392. ;
  1393. ;    int x_set_tripplebuffer(unsigned int PageHeight);
  1394. ;
  1395. ; Params: PageHeight is the height of the virtual screen to tripple buffer
  1396. ;         Returns the closest possible height to the specified.
  1397. ;
  1398. ; Sets up two tripple buffering virtual pages
  1399. ; GLOBAL variables set:
  1400. ;
  1401. ;      _Page1_Offs              Offset of second virtual page
  1402. ;      _Page2_Offs              Offset of third virtual page
  1403. ;      _NonVisual_Offs          Offset of first non visible video ram byte
  1404. ;      _DoubleBufferActive      Flag
  1405. ;      _PageAddrTable           Table of Double buffering pages start offsets
  1406. ;      _ScrnLogicalHeight       Logical height of the double buffering pages
  1407. ;
  1408. ;
  1409. ; Almost written by Tore Bastiansen (cut & paste from _x_set_doublebuffer)
  1410. ;------------------------------------------------------------------------
  1411.  
  1412. _x_set_tripplebuffer proc
  1413.        ARG PageHeight:word
  1414.        push  bp
  1415.        mov   bp,sp
  1416.  
  1417.        cmp   [_DoubleBufferActive],0
  1418.        jne   @@Error
  1419.        cmp   [_TrippleBufferActive],0
  1420.        je    @@OkToContinue
  1421. @@Error:
  1422.        mov   [_ErrorValue],ERROR
  1423.        pop   bp
  1424.        ret
  1425.  
  1426. @@OkToContinue:
  1427.        mov   [_VisiblePageIdx],0     ; Set visible Page to 0
  1428.        mov   ax,[_ScrnLogicalHeight] ; Set Maximum T.B. Page height to
  1429.        mov   bx,3
  1430.        xor   dx,dx
  1431.        idiv  bx                      ;   _ScrnLogicalHeight / 3
  1432.  
  1433.        mov   bx,[PageHeight]         ; Is the require T.B. Page Height
  1434.        cmp   ax,bx                   ;  > the Maximum  T.B. Page Height ?
  1435.  
  1436.        js    @@InvalidHeight         ; no  - jump
  1437.        mov   ax,bx                   ; yes - Set the T.B. Page height to
  1438.                                      ;       to the maximum allowed.
  1439.  
  1440. @@InvalidHeight:
  1441.        mov   [_ScrnLogicalHeight],ax    ; Update logical screen height to
  1442.                                         ;  reflect the height of a T.B. page
  1443.        cmp   ax,[_BottomClip]
  1444.        jle   @@BottomClipOK             ; Adjust Clip Rectangle if necessary
  1445.        mov   [_BottomClip],ax
  1446. @@BottomClipOK:
  1447.        push  ax
  1448.        mul   [_ScrnLogicalByteWidth]    ; Calculate the offset of the second
  1449.        mov   cx,ax                      ;  D.B. Page in video ram
  1450.        mov   bx,[_Page0_Offs]
  1451.        mov   [_VisiblePageOffs],bx
  1452.  
  1453.        add   ax,bx
  1454.        mov   [_Page1_Offs],ax           ; Save it
  1455.        mov   [_HiddenPageOffs],ax
  1456.  
  1457.        add   ax,cx
  1458.        mov   [_Page2_Offs],ax            ; Save the other it ?
  1459.        mov   [_WaitingPageOffs],ax
  1460.  
  1461.        add   ax,cx                       ; Calculate the offset of first byte
  1462.        mov   [_NonVisual_Offs],ax        ;  beyond the D.B. pages and save it
  1463.        mov   [_TrippleBufferActive],TRUE ; Set flag indicating T.B'ing mode on
  1464.  
  1465.        pop   ax
  1466.        sub   ax,[_ScrnPhysicalHeight]
  1467.        add   ax,[_SplitScrnVisibleHeight]
  1468.        mov   [_MaxScrollY],ax
  1469.  
  1470.        mov   ax,dx                      ; return the D.B. pages' height
  1471.        mov   [_ErrorValue],OK
  1472.        pop   bp
  1473.        ret
  1474. _x_set_tripplebuffer endp
  1475.  
  1476.  
  1477. ;-----------------------------------------------------------------------
  1478. ; Set Clipping rectangle
  1479. ; C callable as:
  1480. ;
  1481. ;
  1482. ;    int x_set_cliprect(WORD left,WORD top, WORD right, WORD bottom);
  1483. ;
  1484. ;
  1485. ; NOTE clipping is byte oriented. "left" and "right" are in bytes not pixels.
  1486. ;    Only selected functions perform any clipping at all.
  1487. ;
  1488. ; Written by Themie Gouthas
  1489. ;------------------------------------------------------------------------
  1490.  
  1491. _x_set_cliprect proc
  1492. ARG left:word,top:word,right:word,bottom:word
  1493.        push  bp
  1494.        mov   bp,sp
  1495.        mov   ax,[left]
  1496.        mov   bx,[right]
  1497.        cmp   bx,ax
  1498.        jns   @@CorrectXOrder
  1499.        xchg  bx,ax
  1500. @@CorrectXOrder:
  1501.        mov   [_LeftClip],ax
  1502.        mov   [_RightClip],bx
  1503.        mov   ax,[top]
  1504.        mov   bx,[bottom]
  1505.        cmp   bx,ax
  1506.        jns   @@CorrectYOrder
  1507.        xchg  bx,ax
  1508. @@CorrectYOrder:
  1509.        mov   [_TopClip],ax
  1510.        mov   [_BottomClip],bx
  1511.        pop   bp
  1512.        ret
  1513. _x_set_cliprect endp
  1514.  
  1515.  
  1516. ;----------------------------------------------------------------------
  1517. ; Return to text mode
  1518. ;
  1519. _x_text_mode proc
  1520.        push  bp
  1521.        call  clear_vram
  1522.        mov   ax,03h        ; Restore Text Mode
  1523.        int   10h
  1524.  
  1525.        pop   bp
  1526.        ret
  1527. _x_text_mode endp
  1528.  
  1529. ;-----------------------------------------------------------------------
  1530. ; Wait for Vertical sync
  1531. _x_wait_vsync proc
  1532.     push  bp
  1533.     WaitVsyncStart
  1534.     pop   bp
  1535.     ret
  1536. _x_wait_vsync endp
  1537.  
  1538.  
  1539.     end
  1540.